# -*- coding: UTF-8 -*-

import hashlib
import json
import re
import time

import chardet
import requests
from lxml import html


from teex import *

app_key = 12574478;
jsv = '2.4.2'


def parse_html(url, cookie, params=None, is_json=False, cookie_required=False):
    headers = {
        'User-Agent': 'Mozilla/5.0' '(Windows' 'NT' '10.0;' 'Win64;' 'x64;' 'rv:66.0)' 'Gecko/20100101' 'Firefox/66.0',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Accept-Encoding': 'gzip,' 'deflate,' 'br',
        'Referer': 'https://world.taobao.com/',
        'Connection': 'keep-alive',
        'Cookie': cookie,
        'Upgrade-Insecure-Requests': '1',
        'TE': 'Trailers'
    }
    res = requests.get(url, headers=headers, params=params)
    #print(res.url)
    if is_json == True:
        return json.loads(re.match(".*?({.*}).*", res.text, re.S).group(1))
    elif cookie_required == True:
        #print(res.cookies.get_dict())
        return res.cookies.get_dict(), html.fromstring(
            res.content.decode('utf-8', 'ignore') if chardet.detect(res.content)[
                                                         'encoding'] == 'utf-8' else res.content)
    return html.fromstring(
        res.content.decode('utf-8', 'ignore') if chardet.detect(res.content)['encoding'] == 'utf-8' else res.content)


# 从cookie中解析特定key及value
def get_token(cookie, token_key):
    for pair in cookie.split('; '):
        key, value = pair.split('=')[:2]
        if key == token_key:
            #print(key, value.split('_')[0])
            return value.split('_')[0]


def save_json(fname, data):
    with open(fname, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=True)


# 获取_m_h5_tk及_m_h5_tk_enc cookie
def get_mh5_token(cookie):
    if '_m_h5_tk' in cookie:
        return cookie

    url = 'https://h5api.m.taobao.com/h5/mtop.taobao.mbis.address.geconfigcity/1.0/?jsv=%s&appKey=%d&api=mtop.taobao.mbis.address.geConfigCity&v=1.0&ecode=1&needLogin=true&dataType=jsonp&type=jsonp&callback=mtopjsonp1&data={"configKey":"defaultOverseaData"}' % (
    jsv, app_key)
    c, _ = parse_html(url, cookie, cookie_required=True)
    for key, value in c.items():
        cookie = cookie + '; %s=%s' % (key, value)
    return cookie


# 生成令牌
def generate_sign(token, ts, app_key, data='{}'):
    value = "%s&%s&%s&%s" % (token, ts, app_key, data)
    m = hashlib.md5(value.encode('utf-8'))
    return m.hexdigest()


# 获取用户基本信息：真实姓名，邮箱，性别，出生日期，省市区，详细地址，电话号码，固定电话，是否将固定电话作为交易方式
# 对应网址 https://member1.taobao.com/member/fresh/account_profile.htm
def get_basic_info(cookie):
    url = 'https://member1.taobao.com/member/fresh/account_profile.htm'
    root = parse_html(url, cookie)
    form = root.xpath('//*[@id="ah:addressForm"]/li')
    basic_info = {
        'name': form[0].find('strong').text,
        'email': form[1].find('strong').text,
        'gender': [g.get('value') for g in form[2].findall('span/input') if g.get('checked') is not None][0],
        'birthday': '/'.join([b.get('value') for b in form[3].findall('input')]),
        'location': '/'.join([b.get('value') for b in form[4].findall('p/select')]),
        'details': form[5].find('input').get('value'),
        'zipcode': form[6].find('input').get('value'),
        'line_phone': form[7].find('input[@id="formatPhone"]').get('value'),
        'phone_setting': False if form[8].find('span/input').get('checked') is None else True
    }
    #print(basic_info)
    #save_json('basic_info.json', basic_info)
    return basic_info


# 获取收货地址信息：收件人，所在地区，详细地址，邮编，电话/手机，是否为默认地址，是否需要升级地址(即地址是否可用)
# 对应网址 https://member1.taobao.com/member/fresh/deliver_address.htm
def get_address_info(cookie):
    cookie = get_mh5_token(cookie)
    url = 'http://h5api.m.taobao.com/h5/mtop.taobao.mbis.getdeliveraddrlist/1.0/'
    ts = int(round(time.time() * 1000))
    params = {
        'jsv': jsv,
        'appKey': app_key,
        't': ts,
        'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key),
        'api': 'mtop.taobao.mbis.getDeliverAddrList',
        'v': '1.0',
        'ecode': 1,
        'needLogin': 'true',
        'dataType': 'jsonp',
        'type': 'jsonp',
        'callback': 'mtopjsonp4',
        'data': '{}'
    }
    info = parse_html(url, cookie, params, is_json=True)
    address_info = json.loads(info['data']['returnValue'])
    info_key = ['fullName', 'fullAddress', 'addressDetail', 'post', 'mobile', 'defaultAddress', 'needUpgrade']
    address_lst = [
        {key: address[key] for key in info_key}
        for address in address_info
    ]
    #save_json('address_lst.json', address_lst)
    return address_lst


# 获取收藏夹信息：商品图片地址，商品链接，商品名，商品是否有效，是否为天猫商品，商品所属店铺
# 对应网址 https://shoucang.taobao.com/item_collect.htm
def get_fav(cookie):
    fav_start = 0
    fav_lst = []
    url = 'https://shoucang.taobao.com/item_collect.htm'
    while True:
        fav_info = None
        if fav_start > 0:
            url = 'https://shoucang.taobao.com/nodejs/item_collect_chunk.htm?ifAllTag=0&tab=0&tagId=&categoryCount=0&type=0&tagName=&categoryName=&needNav=false&startRow=%d&t=%d' % (
            fav_start * 30, int(round(time.time() * 1000)))
            root = parse_html(url, cookie)
            fav_info = root.xpath('li')
        else:
            root = parse_html(url, cookie)
            fav_info = root.xpath('//*[@id="fav-list"]/ul/li')
        for f in fav_info:
            fav = {
                'img': f.find('div[@class="img-controller-box J_FavImgController"]/div/a/img').get('src'),
                'href': f.find('div[@class="img-item-title"]/a').get('href'),
                'text': f.find('div[@class="img-item-title"]/a').text,
                'isvalid': not 'isinvalid' in f.get('class'),
                'istmall': 'istmall' in f.get('class'),
                'shop': f.find('div[@class="img-controller-box J_FavImgController"]/a[@class="go-shop-link"]').get(
                    'href')
            }
            fav_lst.append(fav)
        fav_start += 1
        if len(fav_info) < 30:
            break
    return fav_lst
    #save_json('fav_lst.json', fav_lst)


# 获取购物车信息：店铺名，卖家名，[商品id，商品名，商品细节（如鞋码选择等），商品价格，商品图片链接，商品链接]
# 对应网址 https://cart.taobao.com/cart.htm
def get_cart(cookie):
    url = 'https://cart.taobao.com/json/asyncGetMyCart.do'
    params = {
        'isNext': True,
        'endTime': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
        'page': 2,
        '_thwlang': 'zh_CN',
        '_tb_token_': get_token(cookie, '_tb_token_'),
        '_ksTS': '%d_553' % int(round(time.time() * 1000)),
        'callback': 'asyncGetMyCart'
    }
    cart_info = parse_html(url, cookie, params, is_json=True)
    #save_json('cart_info.json', cart_info)
    cart_lst = [
        {
            'shop_name': c['title'],
            'seller': c['seller'],
            'items': [
                [{
                    'id': i['id'],
                    'title': i['title'],
                    'skus': '' if 'skus' not in i.keys() else i['skus'],
                    'price': i['price']['now'] / 1000,
                    'amount': i['amount']['now'],
                    'img': i['pic'],
                    'url': i['url'],
                    'is_valid': i['isValid']
                } for i in o['orders']
                ] for o in c['bundles']
            ]
        }
        for c in cart_info['list']
    ]
    return cart_lst

    #save_json('cart_lst.json', cart_lst)


# 获取已购宝贝信息：支付交易id，支付信息，交易商品详情，卖家信息（店铺名，店铺图片链接，店铺链接，店铺nick，店铺id），交易状态
# 对应网址 https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm
def get_buyertrade(cookie):
    orders_lst = []
    page_num = 1
    page_size = 50
    while True:
        url = 'https://buyertrade.taobao.com/trade/itemlist/asyncBought.htm?action=itemlist/BoughtQueryAction&event_submit_do_query=1&_input_charset=utf8'
        params = {
            'pageNum': page_num,
            'pageSize': page_size,
            'commentStatus': 'ALL',
            'prePageNo': 1
        }
        root = parse_html(url, cookie, params=params, is_json=True)
        orders = root['mainOrders']
        for o in orders:
            order = {
                'id': o['id'],
                'pay_info': o['payInfo'],
                'order_info': o['orderInfo'],
                'sub_order': o['subOrders'],
                'seller': {
                    'shop_name': o['seller']['shopName'] if 'shopName' in o['seller'].keys() else None,
                    'shop_img': o['seller']['shopImg'] if 'shopImg' in o['seller'].keys() else None,
                    'shop_url': o['seller']['shopUrl'] if 'shopUrl' in o['seller'].keys() else None,
                    'shop_nick': o['seller']['nick'] if 'nick' in o['seller'].keys() else None,
                    'shop_id': o['seller']['id'] if 'id' in o['seller'].keys() else None,
                },
                'status': o['statusInfo']
            }
            orders_lst.append(order)
        if page_num >= root['page']['totalPage']:
            break
        else:
            page_num += 1
    return orders_lst
    #save_json('buyertrade.json', orders_lst)


# 获取我的足迹信息：day_cnt每天浏览多少，my_path足迹详情
def get_footmark(cookie):
    cookie = get_mh5_token(cookie)
    url = 'https://h5api.m.taobao.com/h5/mtop.taobao.cmin.daycount/1.0/'
    ts = int(round(time.time() * 1000))
    params = {
        'jsv': jsv,
        'appKey': app_key,
        't': ts,
        'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key),
        'api': 'mtop.taobao.cmin.daycount',
        'v': 1.0,
        'dataType': 'jsonp',
        'type': 'jsonp',
        'callback': 'mtopjsonp3',
        'data': '{}'
    }
    day_cnt = parse_html(url, cookie, params=params, is_json=True)
    #save_json('day_cnt.json', day_cnt)

    url = 'https://h5api.m.taobao.com/h5/mtop.taobao.cmin.mypath/1.0/'
    params = {
        'jsv': jsv,
        'appKey': app_key,
        't': ts,
        'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key, '{"endTime":"%d","pagSize":20}' % ts),
        'api': 'mtop.taobao.cmin.mypath',
        'v': 1.0,
        'dataType': 'jsonp',
        'type': 'jsonp',
        'callback': 'mtopjsonp3',
        'data': '{"endTime":"%d","pagSize":20}' % ts
    }
    my_path = parse_html(url, cookie, params=params, is_json=True)
    #save_json('my_path.json', my_path)
    return my_path


# 获取用户昵称，手机及id
def get_nick_phone_id(cookie):
    url = 'https://member1.taobao.com/member/fresh/account_security.htm'
    root = parse_html(url, cookie)
    phone_num = root.xpath('//ul[@class="account-info"]/li/span[@class="default grid-msg"]')[0].text.strip()

    cookie = get_mh5_token(cookie)
    ts = int(round(time.time() * 1000))
    url = 'https://h5api.m.taobao.com/h5/mtop.user.getusersimple/1.0/'
    params = {
        'jsv': jsv,
        'appKey': app_key,
        't': ts,
        'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key, '{}'),
        'api': 'mtop.user.getUserSimple',
        'v': 1.0,
        'dataType': 'jsonp',
        'type': 'jsonp',
        'callback': 'mtopjsonp3',
        'data': '{}'
    }
    info = parse_html(url, cookie, params=params, is_json=True)
    user_info = {
        'phone_num': phone_num,
        'id': info['data']['userNumId'],
        'nick': info['data']['nick']
    }
    return user_info
    #save_json('nick_phone_id.json', user_info)

def getTaobaoData(cookie):
    result = {}
    try:
        result['basicinfo'] = get_basic_info(cookie)
    except Exception as e:
        print('taobao basicinfo error', e)
    try:
        result['address'] = get_address_info(cookie)
    except Exception as e:
        print('taobao address error', e)
    try:
        result['fav'] = get_fav(cookie)
    except Exception as e:
        print('taobao fav error', e)
    try:
        result['cart'] = get_cart(cookie)
    except Exception as e:
        print('taobao cart error', e)
    try:
        result['footmark'] = get_footmark(cookie)
    except Exception as e:
        print('taobao footmark error', e)
    try:
        result['nickphoneid'] = get_nick_phone_id(cookie)
    except Exception as e:
        print('taobao nickphoneid error', e)
    try:
        result['buyertrade'] = get_buyertrade(cookie)
    except Exception as e:
        print('taobao buytrade error', e)

    return json.dumps(result, sort_keys=True, indent=4, separators=(',', ':'),ensure_ascii=False)

if __name__ == "__main__":
    cookie = TEEX_getinput()

    taobao_info = getTaobaoData(cookie)
    TEEX_return(taobao_info)
